package com.louis.ylog.appender;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.ThrowableProxy;
import ch.qos.logback.core.AppenderBase;
import ch.qos.logback.core.LogbackException;
import com.dianping.cat.Cat;
import com.dianping.cat.message.Message;
import com.louis.ylog.starter.YLogProperties;

import java.io.PrintWriter;
import java.io.StringWriter;

public class CATAppender  extends AppenderBase<ILoggingEvent> {


    private final   boolean enableElk;

    private final boolean enableCat;

    private CATAppender(){
        this(null);
    }

    public boolean isEnableElk(){
        return this.enableElk;
    }

    public boolean isEnableCat(){
        return this.enableCat;
    }

    public CATAppender(YLogProperties logProperties){
        this.enableCat=logProperties!=null&&logProperties.getCat()!=null&&logProperties.getCat().isEnableCat();
        this.enableElk=logProperties!=null&&logProperties.getElk()!=null&&logProperties.getElk().isEnableElk();

        if(this.enableCat){
            Cat.initializeByDomain(String.format("%s-%s",logProperties.getEnv(),logProperties.getAppName()),
                    logProperties.getCat().getPort(),
                    logProperties.getCat().getHttpPort(),
                    logProperties.getCat().getCatServers());
        }
    }

    @Override
    protected void append(ILoggingEvent event) {
        if(this.enableCat){
            appendCat(event);
        }
    }

    protected void appendCat(ILoggingEvent event) {
        try {
            Cat.getManager().setTraceMode(true);

            boolean isTraceMode = Cat.getManager().isTraceMode();
            Level level = event.getLevel();
            if (level.isGreaterOrEqual(Level.ERROR)) {
                logError(event);
            } else if (isTraceMode) {
                logTrace(event);
            }
        } catch (Exception ex) {
            throw new LogbackException(event.getFormattedMessage(), ex);
        }
    }

    private void logError(ILoggingEvent event) {
        ThrowableProxy info = (ThrowableProxy) event.getThrowableProxy();
        if (info != null) {
            Throwable exception = info.getThrowable();

            Object message = event.getFormattedMessage();
            if (message != null) {
                Cat.logError(String.valueOf(message), exception);
            } else {
                Cat.logError(exception);
            }
        }else{
            Object message = event.getFormattedMessage();
            if (message != null) {
                Cat.logError(String.valueOf(message), new Exception("无异常堆栈"));
            }
        }
    }

    private void logTrace(ILoggingEvent event) {
        String type = event.getLoggerName();
        String name = event.getLevel().toString();
        Object message = event.getFormattedMessage();
        String data;
        if (message instanceof Throwable) {
            data = buildExceptionStack((Throwable) message);
        } else {
            data = event.getFormattedMessage();
        }

        ThrowableProxy info = (ThrowableProxy) event.getThrowableProxy();
        if (info != null) {
            data = data + '\n' + buildExceptionStack(info.getThrowable());
        }

        Cat.logEvent(type, name, Message.SUCCESS, data);
    }

    private String buildExceptionStack(Throwable exception) {
        if (exception != null) {
            StringWriter writer = new StringWriter(2048);
            exception.printStackTrace(new PrintWriter(writer));
            return writer.toString();
        } else {
            return "";
        }
    }
}
